//////////////////////////////////////////////////////////////////////////////// // Project : Inverted Pendulum (Slave chip) // // Version : 1.0 // // Date : 4/24/2008 // // Author : Kirk Fitzpatrick // // Company : Private user // // Comments: This chip will manage the position decoding for the penddulum // // using external interupts with quadriture encoding along with // // position decoding of the DC motor Within the main loop. The // // position values will be passed into the SPDR where it can be // // accesed by the Master via the Serial Periphreal Interface(SPI). // // // // Chip type : ATmega8 // // Program type : Application // // Clock frequency : 20.000000 MHz // // Memory model : Small // // External SRAM size : 0 // // Data Stack size : 256 // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // LIBRARY DECLARATION // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include //////////////////////////////////////////////////////////////////////////////// // INTERRUPT DECLARATION // //////////////////////////////////////////////////////////////////////////////// interrupt [EXT_INT0] void ext_int0_isr(void); interrupt [EXT_INT1] void ext_int1_isr(void); //////////////////////////////////////////////////////////////////////////////// // FUNCTION DECLARATION // //////////////////////////////////////////////////////////////////////////////// void mot_position_algorithm(void); //void pen_position_algorithm(void); //////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLE DECLARATION // //////////////////////////////////////////////////////////////////////////////// int pen_position=0; int mot_position=0; char last_motpin_2=0; char last_dir=0xFF,last_called=0xFF; char pwm_high, pwm_low; signed int pwm; //////////////////////////////////////////////////////////////////////////////// // MAIN FUNCTION // //////////////////////////////////////////////////////////////////////////////// void main(void) { //////////////////////////////////////////////////////////////////////////////// // LOCAL VARIABLE DECLARATION // //////////////////////////////////////////////////////////////////////////////// char mot_position_high, mot_position_low; char pen_position_high, pen_position_low; //////////////////////////////////////////////////////////////////////////////// // GPIO initialization // //////////////////////////////////////////////////////////////////////////////// // PORTB contains the pins for SPI comunication. The port is as follows: // // PORTB.1 OCRA OUTPUT // // PORTB.2 SS INPUT // // PORTB.3 MOSI INPUT // // PORTB.4 MISO OUTPUT // // PORTB.5 SCK INPUT // //////////////////////////////////////////////////////////////////////////////// PORTB=0x00; DDRB=0x12; //////////////////////////////////////////////////////////////////////////////// // DIRECTION/MOTER IN // //////////////////////////////////////////////////////////////////////////////// // PORTC.0 DIR OUTPUT // // PORTC.1 DIR OUTPUT // // PORTC.2 MOTOR(ENC) INPUT // // PORTC.3 MOTOR(ENC) INPUT // //////////////////////////////////////////////////////////////////////////////// PORTC=0x00; DDRC=0x03; //////////////////////////////////////////////////////////////////////////////// // PORTD contains the pins for external interupts. The port is as follows: // // PORTB.2 INTO INPUT // // PORTB.3 INT1 INPUT // //////////////////////////////////////////////////////////////////////////////// PORTD=0x00; DDRD=0x00; //////////////////////////////////////////////////////////////////////////////// // Timer/Counter 1 initialization // // Clock source: System Clock // // Clock value: 78.125 kHz // // Mode: Fast PWM top=00FFh // // OC1A output: Inverted // // Noise Canceler: Off // //////////////////////////////////////////////////////////////////////////////// TCCR1A=0xC1; TCCR1B=0x0C; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; //////////////////////////////////////////////////////////////////////////////// // External Interrupt(s) initialization // // INT0/INT1 - Enabled // // INT0/INT1 - Mode: Any change // //////////////////////////////////////////////////////////////////////////////// GICR|=0xC0; MCUCR=0x05; GIFR=0xC0; //////////////////////////////////////////////////////////////////////////////// // USART initialization // // Communication Parameters: 8 Data, 1 Stop, No Parity // // USART Receiver: On // // USART Transmitter: On // // USART Mode: Asynchronous // // USART Baud Rate: 9600 // //////////////////////////////////////////////////////////////////////////////// UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x81; //////////////////////////////////////////////////////////////////////////////// // Analog Comparator initialization // // Analog Comparator: Off // //////////////////////////////////////////////////////////////////////////////// ACSR=0x80; SFIOR=0x00; //////////////////////////////////////////////////////////////////////////////// // SPI initialization // // SPI Type: Slave // // SPI Clock Rate: 1250.000 kHz // // SPI Clock Phase: Cycle Half // // SPI Clock Polarity: Low // // SPI Data Order: MSB First // //////////////////////////////////////////////////////////////////////////////// SPCR=0x41; SPSR=0x00; // Global enable interrupts #asm("sei") while (1) { //////////////////////////////////////////////////////////////////////////////// // SPI DATA CONTITIONING // //////////////////////////////////////////////////////////////////////////////// pen_position_high=pen_position>>8; pen_position_low=pen_position; mot_position_high=mot_position>>8; mot_position_low =mot_position; //////////////////////////////////////////////////////////////////////////////// // SPI DATA TRANSFER (BIG ENDIAN) // //////////////////////////////////////////////////////////////////////////////// if(~PINB.2){ #asm("cli") spi(0); spi(0); pwm_high=spi(pen_position_high); pwm_low=spi(pen_position_low); spi(mot_position_high); spi(mot_position_low); #asm("sei") pwm=((signed int)pwm_high)<<8|pwm_low; OCR1AH=OCR1AL=abs(pwm); PORTC =(PORTC&0xFC)|((pwm<0)?0x01:0x02); } //////////////////////////////////////////////////////////////////////////////// // CALLS THE QUADRATURE ALGORITHM TO UPDATE THE MOTOR POSITION // //////////////////////////////////////////////////////////////////////////////// mot_position_algorithm(); }; } //////////////////////////////////////////////////////////////////////////////// // EXTERNAL INTERRUPT SERVICE ROUTINE TO UPDATE THE CURRENT PENDULUM POSITION // //////////////////////////////////////////////////////////////////////////////// interrupt [EXT_INT0] void ext_int0_isr(void) { char dir = PIND.2^PIND.3; if(last_called!=0||last_dir!=dir); pen_position+=(last_dir=dir)?1:-1; last_called = 0; } interrupt [EXT_INT1] void ext_int1_isr(void) { char dir = !(PIND.2^PIND.3); if(last_called!=0||last_dir!=dir); pen_position+=(last_dir=dir)?1:-1; last_called = 1; } //////////////////////////////////////////////////////////////////////////////// // THIS FUNCTION PERFORMS AN ALGORITHM TO UPDATE THE MOTOR POSITION // //////////////////////////////////////////////////////////////////////////////// void mot_position_algorithm(void) { if(PINC.2!=last_motpin_2){ if(PINC.2){ mot_position+=PINC.3?1:-1; } } last_motpin_2=PINC.2; }